#include "stdafx.h"

#include "VideoCapture_AvtUniAPI.h"
#include <colour_conv.h>

#ifndef NO_AVT_UNIAPI

AvtUniAPI::AvtUniAPI()
{
	if(this->verbose) std::clog<<"AvtUniAPI() called.\n";
	this->rawImage = NULL;
	this->initialised = false;
	this->ImageBuffer = NULL;
	this->verbose = true;
	this->width = 640;
	this->height = 480;
	this->cnt = 0;
	this->selectedCamId = 0;
	this->interacedCapture = false;
	this->CamIds.resize(64);
	this->opened = false;
}


AvtUniAPI::~AvtUniAPI()
{
	if(this->verbose) std::clog<<"~AvtUniAPI() called.\n";
	if(this->initialised) {
		this->closeCam();
	}
}

bool AvtUniAPI::initCam() {
	if(!this->initialised) {
		this->Result = UCC_Init();
		if( Result == UNI_RESULT_API_NOT_INITIALIZED )        
		{
			if(this->verbose) std::cout<<"AvtUniAPI::UCC_init() failed\n";
			return false;
		} else {
			if(Result == S_OK ) {
			if(this->verbose) std::clog<<"AvtUniAPI::UCC_init() success\n";
			} else {
			if(this->verbose) std::clog<<"AvtUniAPI::UCC_init() may be already initialised.\n";
			}
			this->initialised = true;
		}
	}
	return true;
}

int AvtUniAPI::probeCam(unsigned long manualIPaddress ) {
	if(!this->initialised) {
		this->initCam();
	}
	this->cnt = 64;
	//this->CamIds.clear();
    this->Result = UCC_GetCameras(&this->cnt,&*this->CamIds.begin());
	if( S_OK != Result && UNI_RESULT_MORE_DATA != Result)
    {
		if(this->verbose) cerr<<"UCC_GetCameras() failed, program execution stopped.\n";
		return 0;
	}
	if(this->verbose) std::cout<< (long)this->cnt <<" cameras found\n";
	return (int) cnt;
}

bool AvtUniAPI::getCamId(int index, unsigned long &camId, std::string *camName) {
	if(!this->initialised) {
		this->initCam();
	}
	if(!(index < (int) this->cnt)) {
		if(this->verbose) std::cerr<<"Camera index out of bound\n";
		return false;
	}
	camId = this->CamIds.at(index);
	if(camName!=NULL) {
		Result = UCC_OpenCamera(this->CamIds.at(index));
		if(S_OK !=this->Result)
		{
			if(this->verbose) std::cerr<<"UCC_OpenCamera() failed, program execution stopped.Result is"<<Result<<"\n";
			return false;
		}
		char model[128];
		UINT32_TYPE msize(128);
		UCC_GetCameraInfoString( this->CamIds.at(index),E_CAMINFO_MODEL,model,&msize);
		camName->assign(model);
		this->Result = UCC_CloseCamera(this->CamIds.at(index));
		if(S_OK != this->Result)
		{
			if(this->verbose) std::cerr<<"UCC_CloseCamera failed.\n";
			return false;
		}
	}
	return true;
}

bool AvtUniAPI::openCam(unsigned long camId) {
	if(!this->initialised) {
		this->initCam();
	}
	if(this->opened) {
		if(this->verbose) std::cout<<"Camera is already opened. Force closing opened camera.\n";
		this->closeCam();
	}
	this->selectedCamId = (UINT32_TYPE) camId;
		this->Result = UCC_OpenCamera(selectedCamId);
	if(S_OK !=this->Result)
	{
		if(this->verbose) std::cerr<<"UCC_OpenCamera() failed, program execution stopped.Result is"<<Result<<endl;
		return false;
	}
	this->Result = UCC_GetCameraInfo(this->selectedCamId,E_CAMINFO_BAYERPATTERN,&this->BayerPattern);
	this->Result = UCC_GetCameraInfo(this->selectedCamId,E_CAMINFO_INTERLACED,&this->Intelaced);
	if(this->Intelaced) this->interacedCapture = true;
	this->Result = UCC_GetCameraInfo(this->selectedCamId,E_CAMINFO_INTERFACETYPE,&this->Interface);	
	UINT32_TYPE nMode = 0;
	UINT32_TYPE nColorFormat = E_CC_RAW8;
	UINT32_TYPE nHorizontalResolution = this->width;
	UINT32_TYPE nVerticalResolution = this->height;
	UINT32_TYPE nBayerPattern =E_BP_AUTO;
	this->Result = UCC_PrepareFreeGrab(this->selectedCamId,&nMode, &nColorFormat, &nHorizontalResolution, &nVerticalResolution, NULL, NULL, NULL, NULL);
	if(S_OK != this->Result)
	{
		if(this->verbose) std::cerr<<"UCC_PrepareFreeGrab() failed, program execution stopped.\n";
		return false;
	}
	this->Result = UCC_GetCurrentImageFormat(  this->selectedCamId, &this->ImageWidth, &this->ImageHeight, &this->ColorCoding, &this->ImageDepth );
	if(S_OK != this->Result)
	{
		if(this->verbose) std::cerr<<"UCC_GetCurrentImageFormat() failed, program execution stopped.\n";
		return false;
	}
	UINT32_TYPE shutterSpeed;
	this->Result = UCC_GetFeatureValue  (this->selectedCamId, E_FEAT_SHUTTER, &shutterSpeed);
	if(S_OK != this->Result)
	{
		if(this->verbose) std::cerr<<"UCC_GetFeatureValue failed, program execution stopped.\n";
		return false;
	}
	UINT32_TYPE shutterTimeBase;
	this->Result = UCC_GetFeatureValue  (this->selectedCamId, 	E_FEAT_TIMEBASE , &shutterTimeBase);
	if(S_OK != this->Result)
	{
		if(this->verbose) std::cerr<<"UCC_GetFeatureValue failed, program execution stopped.\n";
		return false;
	}
	switch(shutterTimeBase) {
	case 0 : shutterSpeed *= 1;
		break;
	case 1: shutterSpeed *= 2;
		break;
	case 2: shutterSpeed *= 5;
		break;
	case 3: shutterSpeed *= 10;
		break;
	case 4: shutterSpeed *= 20;
		break;
	case 5: shutterSpeed *= 50;
		break;
	case 6: shutterSpeed *= 100;
		break;
	case 7: shutterSpeed *= 200;
		break;
	case 8: shutterSpeed *= 500;
		break;
	case 9: shutterSpeed *= 1000;
		break;
	}
	if(this->verbose) std::cout<<"Current image format:"<<(long)this->ImageWidth<<"x"<< (long)this->ImageHeight<<" Pixels, Color Format:"<<this->GetColorString(this->ColorCoding)<<(long)this->ImageDepth <<" BPP at "<<(long)shutterSpeed<<"us\n";
	this->SizeInBytes = this->ImageHeight*this->ImageWidth*4*((this->ImageDepth+7)/8);
	this->ImageBuffer = new char[SizeInBytes];
	if(this->ImageBuffer==NULL) {
		if(this->verbose) std::cerr<<"Memory allocate error\n";
		return false;
	}
	this->rawImage = cvCreateImageHeader(cvSize((int)this->ImageWidth, (int)this->ImageHeight), IPL_DEPTH_8U, 1); // rawImage as 1-byte set
	this->rawImage->widthStep = this->rawImage->width;// * 3;
	this->rawImage->imageData = (char *)this->ImageBuffer;	// Points the image to the buffer of the camera
	this->pImage.sImageData.pImageAsSinglePlane = (UINT8_TYPE *) this->ImageBuffer;
	//rgbImage = cvCreateImage(cvSize((int)ImageWidth, (int)ImageHeight), IPL_DEPTH_8U, 3); 	// Create an image (24 bits RGB Color image)
	this->Result = UCC_GrabStart(this->selectedCamId,6000);
			if(S_OK != this->Result)
	{
		if(this->verbose) std::cerr<<"UCC_GrabStart failed.\n";
	}
	this->initialised = true;
	this->opened = true;
	return true;
}



IplImage* AvtUniAPI::grabRawImage() {
	this->Result = UCC_GetNativeImageEx ( this->selectedCamId, (UINT8_TYPE*) this->ImageBuffer, &this->formatInfo, NULL, 6000); // rawImage into rawImage structure even more than 8bpp , async
	if(this->Result!=S_OK) // Grab unsuccessful
	{
		if(this->verbose) {
			char error_text[256];
			UCC_GetErrorInfo(this->Result,error_text,256);
			std::cerr<<"Image Grab Error #"<<error_text<<"\n";
		}
	}
	return this->rawImage;
}

bool AvtUniAPI::getCamProperties(unsigned long propId, unsigned long &value) {
	UINT32_TYPE convertedValue;
	this->Result = UCC_GetFeatureValue(this->selectedCamId, (UINT32_IN_TYPE) propId, &convertedValue);
	value = (unsigned long) convertedValue;
	if(this->Result != S_OK) return false;
	return true;
}

bool AvtUniAPI::setCamProperties(unsigned long propId, unsigned long value) {
	UINT32_TYPE convertedValue = (UINT32_TYPE) value;
	this->Result  = UCC_SetFeatureValue(this->selectedCamId, propId, convertedValue);
	if(this->Result != S_OK) return false;
	return true;
}

bool AvtUniAPI::setImageSize(unsigned int width, unsigned int height, unsigned int bytesPerChannel, unsigned int channels) {
	this->width = (UINT32_TYPE) width;
	this->height = (UINT32_TYPE) height;
	return true;
}

std::string AvtUniAPI::GetColorString( UINT32_TYPE ColorCode)
{
	switch(ColorCode)
	{
	case E_CC_MONO8:    return string("Mono8") ;
	case E_CC_MONO12:   return string("Mono12") ;
	case E_CC_MONO16:   return string("Mono16") ;
	case E_CC_SMONO12:  return string("SMono12") ;
	case E_CC_SMONO16:  return string("SMono16") ;
	case E_CC_RAW8:     return string("Raw8") ;
	case E_CC_RAW12:    return string("Raw12") ;
	case E_CC_RAW16:    return string("Raw16") ;
	case E_CC_RGB8:     return string("RGB8") ;
	case E_CC_RGB12:    return string("RGB12") ;
	case E_CC_RGB16:    return string("RGB16") ;
	case E_CC_SRGB12:   return string("SRGB12") ;
	case E_CC_SRGB16:   return string("SRGB16") ;
	case E_CC_YUV411:   return string("YUV411") ;
	case E_CC_YUV422:   return string("YUV422") ;
	case E_CC_YUV444:   return string("YUV444") ;
	default: return string("Unknown");
	}
}	

bool AvtUniAPI::closeCam(){
	// Stop the acquisition & free the camera
	if(this->ImageBuffer!=NULL) {
		delete this->ImageBuffer;
		this->ImageBuffer = NULL;
	}
	if(this->opened) {
	this->Result = UCC_GrabStop( this->selectedCamId,0);
	if(S_OK != this->Result)
	{
		if(this->verbose) std::cerr<<"UCC_GrabStop failed.\n";
		//return false;
	}
		this->Result = UCC_CloseCamera( this->selectedCamId);
		if(S_OK != this->Result)
		{
			if(this->verbose) std::cerr<<"UCC_CloseCamera failed.\n";
			//return false;
		}
		if(this->verbose) std::cout<<"Capture finished\n.";
	}
	if(this->initialised) {
		this->Result = UCC_Release();  
		if(S_OK != this->Result)
		{
			if(this->verbose) std::cerr<<"UCC_CloseCamera failed.\n";
			//return false;
		}
	}
	this->opened = false;
	this->initialised = false;
	return true;
}




	//this->rgbImage = NULL;
	//initialised = false;
	//bufferLocked = false;
//	CamIds.resize(64);
//	selectedCam = -1;
//	CamInfoStringSet.resize(64);
//	CamInfoValueSet.resize(64);
//	 

	//this->OpenCVCaptureProsilicaGigECamera();
//}
//	//if(rawImage!=NULL) cvReleaseImage(&rawImage);
//	//	if(myCamera.Frame.ImageBuffer!=NULL) cvFree(&myCamera.Frame.ImageBuffer);
//	if(rgbImage!=NULL) cvReleaseImage(&rgbImage);
//	if(bufferLocked) delete ImageBuffer;
//	Result = UCC_Release();
//		if(S_OK != Result)
//	{
//		std::cerr<<"UCC_Release failed.\n";
//	}
//}

//int AvtUniAPI::countCameras()
//{
//	//CloseCamera(); // clean up when bus topology changes
//
//    // get list of cameras found on the bus
//	//CamId = CamIds.at(0);
//}

//bool AvtUniAPI::ListCameras(int i) {
//	char vendor[128],model[128],str[128];
//	UINT32_TYPE vsize(128),msize(128),strSize(128),strSize2(128);
//	UINT32_TYPE value(128);
//	//for(int i=0; i<numCamera; i++) {
//		CamId = CamIds.at(i);
//	Result = UCC_OpenCamera(CamId);
//	if(S_OK !=Result)
//	{
//		cout<<"UCC_OpenCamera() failed, program execution stopped.Result is"<<Result<<endl;
//		return false;
//	}
//	char infoStr[128];
//	UINT32_TYPE strLength(128);
//	UINT32_TYPE infoValue(128);
//	CamInfoStringSet.at(i).resize(E_CAMINFO_LAST);
//	CamInfoValueSet.at(i).resize(E_CAMINFO_LAST);
//	for(int infoId = 0; infoId<E_CAMINFO_LAST; infoId++) {
//		Result = UCC_GetCameraInfoString(CamId,infoId,infoStr,&strLength);
//		if(S_OK == Result) {
//			CamInfoStringSet.at(i).at(infoId).assign(infoStr);
//			UCC_GetCameraInfo(CamId,infoId,&infoValue);
//			CamInfoValueSet.at(i).at(infoId) = infoValue;
//			std::cout<<"CODE #"<<infoId<<": "<<CamInfoStringSet.at(i).at(infoId)<<"\n";
//		}
//	}
//		//std::cout<<"CAM #"<<i<<" "<<CamId<<endl;
//		//UCC_GetCameraInfoString( CamId,E_CAMINFO_VENDOR,vendor,&vsize);
//		//std::cout<<"E_CAMINFO_VENDOR : "<<vendor<<endl;
//		//UCC_GetCameraInfoString( CamId,E_CAMINFO_MODEL,model,&msize);
//		////CamNames.at(i).assign(model);
//		//std::cout<<"E_CAMINFO_MODEL : "<<model<<endl;
//		//UCC_GetCameraInfo( CamId,E_CAMINFO_MAXWIDTH,&value);
//		//std::cout<<"E_CAMINFO_MAXWIDTH : "<<value<<endl;
//		//UCC_GetCameraInfo( CamId,E_CAMINFO_MAXHEIGHT,&value);
//		//std::cout<<"E_CAMINFO_MAXHEIGHT : "<<value<<endl;
//		//UCC_GetCameraInfo( CamId,E_CAMINFO_MAXDEPTH,&value);
//		//std::cout<<"E_CAMINFO_MAXDEPTH : "<<value<<endl;
//		//UCC_GetCameraInfoString( CamId,E_CAMINFO_COLORCAMERA,str,&strSize);
//		//std::cout<<"E_CAMINFO_COLORCAMERA : "<<str<<endl;
//		//UCC_GetCameraInfoString( CamId,E_CAMINFO_BAYERPATTERN ,str,&strSize2); 
//		//std::cout<<"E_CAMINFO_BAYERPATTERN : "<<str<<endl;
//		//UCC_GetCameraInfo( CamId,E_CAMINFO_BAYERPATTERN ,&value); 
//		//std::cout<<"E_CAMINFO_BAYERPATTERN (in value): "<<value<<endl;
//		//this->BayerPattern = value;
//		//UCC_GetCameraInfo( CamId,E_CAMINFO_INTERLACED ,&value); 
//		//std::cout<<"E_CAMINFO_INTERLACED (in value): "<<value<<endl;
//		//this->Intelaced = value;
//		//UCC_GetCameraInfo( CamId,E_CAMINFO_INTERFACETYPE  ,&value); 
//		//std::cout<<"E_CAMINFO_INTERFACETYPE  (in value): "<<value<<endl;		 
//		//this->Interface = value;
//
//
//	//}
//		return true;
//}



//bool AvtUniAPI::capture_init()
//{
//	// Initialize the API. Hint:Always check the function call results
//	if(initialised) {
//		std::cout<<"AvtUniAPI is already initialised"<<endl;
//		return initialised;
//	}
//	initialised = false;
//	//Result = UCC_Init();  
//	//if( FAILED (Result) )        
//	//{
//	//	cout<<"UCC_init() failed, program execution stopped.\n";
//	//	return false;
//	//}
//	//numCamera = countCameras();
//	//if(!(numCamera>0)) {
//	//	return false;
//	//}
//	// try opening the camera with the CAM_ID (serial number)
//	//Result = UCC_OpenCamera(CamId);
//	//if(S_OK !=Result)
//	//{
//	//	cout<<"UCC_OpenCamera() failed, program execution stopped.Result is"<<Result<<endl;
//	//	return false;
//	//}
//	//this->ListCameras();
//	this->BayerPattern = CamInfoValueSet.at(selectedCam).at(E_CAMINFO_BAYERPATTERN);
//	this->Intelaced = CamInfoValueSet.at(selectedCam).at(E_CAMINFO_INTERLACED);
//	this->Interface = CamInfoValueSet.at(selectedCam).at(E_CAMINFO_INTERFACETYPE);
//	/* Get information about the camera's current image format */
//	UINT32_TYPE nMode = 0;
//	UINT32_TYPE nColorFormat = E_CC_RAW8;
//	UINT32_TYPE nHorizontalResolution = 640;
//	UINT32_TYPE nVerticalResolution = 480;
//	UINT32_TYPE nBayerPattern =E_BP_AUTO;
//	Result = UCC_PrepareFreeGrab(CamId,&nMode, &nColorFormat, &nHorizontalResolution, &nVerticalResolution, NULL, NULL, NULL, NULL);
//	if(S_OK != Result)
//	{
//		cout<<"UCC_PrepareFreeGrab() failed, program execution stopped.\n";
//		return false;
//	}
//	Result = UCC_GetCurrentImageFormat(  CamId, &ImageWidth, &ImageHeight, &ColorCoding, &ImageDepth );
//	if(S_OK != Result)
//	{
//		cout<<"UCC_GetCurrentImageFormat() failed, program execution stopped.\n";
//		return false;
//	}
//	UINT32_TYPE shutterSpeed;
//	Result = UCC_GetFeatureValue  (CamId, E_FEAT_SHUTTER, &shutterSpeed);
//	if(S_OK != Result)
//	{
//		cout<<"UCC_GetFeatureValue failed, program execution stopped.\n";
//		return false;
//	}
//	UINT32_TYPE shutterTimeBase;
//	Result = UCC_GetFeatureValue  (CamId, 	E_FEAT_TIMEBASE , &shutterTimeBase);
//	if(S_OK != Result)
//	{
//		cout<<"UCC_GetFeatureValue failed, program execution stopped.\n";
//		return false;
//	}
//	switch(shutterTimeBase) {
//	case 0 : shutterSpeed *= 1;
//		break;
//	case 1: shutterSpeed *= 2;
//		break;
//	case 2: shutterSpeed *= 5;
//		break;
//	case 3: shutterSpeed *= 10;
//		break;
//	case 4: shutterSpeed *= 20;
//		break;
//	case 5: shutterSpeed *= 50;
//		break;
//	case 6: shutterSpeed *= 100;
//		break;
//	case 7: shutterSpeed *= 200;
//		break;
//	case 8: shutterSpeed *= 500;
//		break;
//	case 9: shutterSpeed *= 1000;
//		break;
//	}
//	cout<<"Current image format:"<<(long)ImageWidth<<"x"<< (long)ImageHeight<<" Pixels, Color Format:"<<GetColorString(ColorCoding)<<(long)ImageDepth <<" BPP at "<<(long)shutterSpeed<<"us\n";
//
//	// Determine and allocate the amount of memory needed for an image
//	SizeInBytes = ImageHeight*ImageWidth*4*((ImageDepth+7)/8);
//	ImageBuffer = new char[SizeInBytes];
//	if(ImageBuffer!=NULL) bufferLocked = true;
//	rawImage = cvCreateImageHeader(cvSize((int)ImageWidth, (int)ImageHeight), IPL_DEPTH_8U, 1); // rawImage as 1-byte set
//	rawImage->widthStep = rawImage->width;// * 3;
//	rawImage->imageData = (char *)ImageBuffer;	// Points the image to the buffer of the camera
//	pImage.sImageData.pImageAsSinglePlane = (UINT8_TYPE *) ImageBuffer;
//	rgbImage = cvCreateImage(cvSize((int)ImageWidth, (int)ImageHeight), IPL_DEPTH_8U, 3); 	// Create an image (24 bits RGB Color image)
//	Result = UCC_GrabStart(CamId,6000);
//			if(S_OK != Result)
//	{
//		std::cerr<<"UCC_GrabStart failed.\n";
//	}
//	initialised = true;
//	return true;
//}


//
//void  AvtUniAPI::capture_image() {
//	// Grab one image
//	//Result = UCC_GrabBitmap24Image  ( CamId, (UINT8_TYPE*) ImageBuffer, 6000);
//	//Result = UCC_GrabNativeImageEx ( CamId, (UINT8_TYPE*) ImageBuffer, &formatInfo, &IsColor, 6000); // rawImage into rawImage structure even more than 8bpp, sync
//	//Result = UCC_GrabNativeImage ( CamId, (UINT8_TYPE*) ImageBuffer, &IsColor, 6000); // rawImage into rawImage structure even more than 8bpp, sync
//	Result = UCC_GetNativeImageEx ( CamId, (UINT8_TYPE*) ImageBuffer, &formatInfo, NULL, 6000); // rawImage into rawImage structure even more than 8bpp , async
//	//Result = UCC_GrabImageEx  ( CamId, &pImage, &formatInfo , &IsColor, 6000); // raw became mono, sync
//	//Result = UCC_GrabBitmapImage( CamId, (UINT8_TYPE*) ImageBuffer, &IsColor, 6000);
//	if(Result==S_OK) // Grab successful
//	{
////		if(IsColor) {
//
////		} else { // 1 value per pixel
//		if(this->Intelaced) { // have to be something to check whether it's CYGM model
//			//Result = UIT_IRaw8CYGMToBGR((char *)rgbImage->imageData,(UINT8_TYPE*) ImageBuffer,ImageWidth,ImageHeight,E_BP_CYGM); // Debayering of F-038C CYGM bayer filter
//			demosaicingNakedInteraced((char*) ImageBuffer, rgbImage->imageData, rgbImage->width, rgbImage->height, rgbImage->width, rgbImage->widthStep);
//		} else {
//			//Result = UIT_Raw8ToBGR((char *)rgbImage->imageData,(UINT8_TYPE*) ImageBuffer,ImageWidth,ImageHeight,E_BP_AUTO); 
//			//demosaicingGRGB((char*) ImageBuffer,rgbImage->imageData,rgbImage->width,rgbImage->height,rawImage->widthStep,rgbImage->widthStep);
//			//demosaicingNaked((char*) ImageBuffer,rgbImage->imageData,rgbImage->width,rgbImage->height,rawImage->widthStep,rgbImage->widthStep);
//			cvCvtColor(rawImage, rgbImage,  CV_BayerBG2BGR);
//			//cvCvtColor(rawImage, rgbImage,  CV_BayerBG2BGR_VNG);
//		}
////		}
//		
//	} else {
//		char error_text[256];
//		UCC_GetErrorInfo(Result,error_text,256);
//		std::cerr<<"Image Grab Error #"<<error_text<<"\n";
//	}
//}




#endif
